package org.cyhz.standardize.service;

import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map.Entry;

import org.cyhz.domain.AutoInfoVO;
import org.cyhz.domain.SbVO;
import org.cyhz.domain.SsVO;
import org.cyhz.domain.TimeWindow;
import org.cyhz.standardize.dao.CarInfoDao;
import org.cyhz.util.Log;
import org.cyhz.util.TimeWindowUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("bSStandardizeStep1Service")
public class BSStandardizeStep1ServiceImp implements BSStandardizeStepService {

	@Autowired
	private CarInfoDao carInfoDao;

	@Value("#{configSettings['step1.time.window.width']}")
	private int timeWindowWidth;

	@Value("#{configSettings['startdate']}")
	private String startDate;

	@Value("#{configSettings['enddate']}")
	private String endDate;

	@Autowired
	private DateFormat datetimeFormat;
	@Autowired
	private DateFormat dateFormat;

	public Date getStartDate() throws ParseException {
		return dateFormat.parse(this.startDate);
	}

	public Date getEndDate() throws ParseException {

		Date d = null;
		if (null == this.endDate || this.endDate.trim().equals("")) {
			d = new Date();
		} else {
			d = dateFormat.parse(this.endDate);
		}
		d = TimeWindowUtil.getLastSecondOfDay(d);
		return d;
	}

	@Override
	public void standardize() throws SQLException {

		Date startDate = null;
		Date endDate = null;
		try {
			startDate = this.getStartDate();
		} catch (ParseException e) {
			Log.error("get startDate error", e);
		}

		try {
			endDate = this.getEndDate();
		} catch (ParseException e) {
			Log.error("get endDate error", e);
		}

		List<TimeWindow> timeWindows = null;
		try {
			timeWindows = TimeWindowUtil.getContiguousTimeWindows(
					this.getStartDate(), this.getEndDate(), timeWindowWidth);

			for (TimeWindow tw : timeWindows) {
				Log.info(datetimeFormat.format(tw.getStartDate()) + " to "
						+ datetimeFormat.format(tw.getEndDate()));
			}

		} catch (ParseException e) {
			Log.error("build contiguous time window error", e);
		}

		if (null != timeWindows) {
			for (TimeWindow tw : timeWindows) {
				Log.info(" start step1 "
						+ datetimeFormat.format(tw.getStartDate()) + " to "
						+ datetimeFormat.format(tw.getEndDate()));

				List<Entry<SbVO, List<SsVO>>> sbvos = new ArrayList<>(
						StandardizeResources.sbssMapping.entrySet());

				while (!sbvos.isEmpty()) {
					Entry<SbVO, List<SsVO>> sbss = sbvos.remove(0);

					String sb = sbss.getKey().getSbrand();

					List<String> b = new ArrayList<>();

					if (StandardizeResources.sbnbMapping.containsKey(sb)) {
						b.addAll(StandardizeResources.sbnbMapping.get(sb));
					}

					b.add(sbss.getKey().getSbrand());

					for (SsVO ssvo : sbss.getValue()) {

						String ss = ssvo.getSeries();
						List<String> s = new ArrayList<>();
						if (StandardizeResources.ssnsMapping.containsKey(ss)) {
							s.addAll(StandardizeResources.ssnsMapping.get(ss));
						}
						s.add(ss);
						List<AutoInfoVO> ais = carInfoDao
								.getSimpleNbSbByNbNsAndReleaseTime(b, s,
										tw.getStartDate(), tw.getEndDate());

						if ((null != ais) && (!ais.isEmpty())) {
							Log.debug("get " + ais.size()
									+ " records can directly set " + sb + "|"
									+ ss
									+ datetimeFormat.format(tw.getStartDate())
									+ " to "
									+ datetimeFormat.format(tw.getEndDate()));

							for (AutoInfoVO ai : ais) {
								int effectRows = carInfoDao
										.updateSbSsByNbNs(
												sb,
												ss,
												ai.getBrand(),
												ai.getSeries(),
												TimeWindowUtil
														.getFirstSecondOfDay(startDate),
												TimeWindowUtil
														.getLastSecondOfDay(endDate));
								Log.info("update " + effectRows + " "
										+ ai.getBrand() + "|" + ai.getSeries()
										+ " to " + sb + "|" + ss);
							}
						} else {
							Log.debug("step1 no records can directly set to "
									+ sb + "|" + ss + " remain sb "
									+ sbvos.size());
						}
					}
					Log.info("directly update to " + sb + " done remain sb "
							+ sbvos.size());

				}
				Log.info(" step1 " + datetimeFormat.format(tw.getStartDate())
						+ " to " + datetimeFormat.format(tw.getEndDate())
						+ " finished");
			}
		}

	}
}
